package org.jrpc.core.factory;

import org.jrpc.annotation.JFeign;
import org.jrpc.base.IClient;
import org.jrpc.base.IClientManage;
import org.jrpc.client2.RpcProxy;
import org.jrpc.common.utils.ClassScanUtils;
import org.jrpc.proxy.MyProxyFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.util.Arrays;
import java.util.Set;

/**
 * Created by chenyuncong on 2018/7/19.
 */
public class JRpcDefinitionPostProcessor implements BeanDefinitionRegistryPostProcessor ,EnvironmentAware,ResourceLoaderAware {

    private ResourceLoader resourceLoader;

    private Environment environment;

    private final Set<String> packagesToScan;

//    @Autowired
//    @Qualifier("rpcProxy")
    private RpcProxy rpcProxy;

    private IClient iClient;

    private IClientManage iClientManage;

    public JRpcDefinitionPostProcessor(String... packagesToScan){
        this((Set<String>) Arrays.asList(packagesToScan));
    }

    public JRpcDefinitionPostProcessor(Set<String> packagesToScan) {

        this.packagesToScan = packagesToScan;
    }
    public JRpcDefinitionPostProcessor(Set<String> packagesToScan, RpcProxy rpcProxy) {

        this.packagesToScan = packagesToScan;
        this.rpcProxy = rpcProxy;
    }
    public JRpcDefinitionPostProcessor(Set<String> packagesToScan,IClient iClient) {

        this.packagesToScan = packagesToScan;
        this.iClient = iClient;
    }

    public JRpcDefinitionPostProcessor(Set<String> packagesToScan,IClientManage iClientManage) {

        this.packagesToScan = packagesToScan;
        this.iClientManage = iClientManage;
    }
    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
//        environment.resolvePlaceholders()
//        System.out.println(environment.getProperty("server.port"));
//        System.out.println("packagesToScan:"+packagesToScan.size());
//        System.out.println("setEnvironment");
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
//        ClassPathBeanDefinitionScanner scanner=new ClassPathBeanDefinitionScanner(registry);
//        AnnotationScanner scanner = AnnotationScanner.getScanner(registry, JFeign.class);
        JRpcClassPathBeanDefinitionScanner scanner = new JRpcClassPathBeanDefinitionScanner(registry,environment,resourceLoader);
//        resourceLoader.getClassLoader().getResource()
        scanner.setResourceLoader(resourceLoader);
        scanner.addIncludeFilter(new AnnotationTypeFilter(JFeign.class, true, true));
        int count = scanner.scan("com.cn.server");
        System.out.println("count:"+count);

        Set<BeanDefinition> beanDefinitions = scanner.findCandidateComponents("com.cn.server");

        System.out.println(beanDefinitions.size());

        Set<Class<?>> set = ClassScanUtils.getClasses("com.cn.server");

        for (Class s : set) {
            JFeign jFeign = (JFeign) s.getAnnotation(JFeign.class);
            if(jFeign!=null){
                System.out.println(jFeign.value());
                System.out.println(s.getName());

//                BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(s);
//                System.out.println(beanDefinitionBuilder);
                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(s);
                GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
                definition.getPropertyValues().add("interfaceClass", definition.getBeanClassName());
                definition.getPropertyValues().add("iClientManage", this.iClientManage);
                definition.getPropertyValues().add("serviceName", jFeign.value());

                definition.setBeanClass(MyProxyFactory.class);
                definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
                registry.registerBeanDefinition(jFeign.value(), definition);
            }

        }

        System.out.println("postProcessBeanDefinitionRegistry");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
//        AnnotationScanner annotationScanner =new AnnotationScanner()
//        AnnotationScanner scanner = AnnotationScanner.getScanner((BeanDefinitionRegistry) beanFactory, JFeign.class);
//        System.out.println(scanner);
//

        System.out.println("postProcessBeanFactory");
    }


    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}
